/*
 * Created on Jun 1, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package org.owasp.webgoat.lessons;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.apache.ecs.Element;
import org.apache.ecs.ElementContainer;
import org.apache.ecs.html.A;
import org.apache.ecs.html.BR;
import org.apache.ecs.html.IMG;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.P;
import org.apache.ecs.html.PRE;

import org.owasp.webgoat.session.DatabaseUtilities;
import org.owasp.webgoat.session.ECSFactory;
import org.owasp.webgoat.session.WebSession;

/*******************************************************************************
 * 
 * 
 * This file is part of WebGoat, an Open Web Application Security Project
 * utility. For details, please see http://www.owasp.org/
 * 
 * Copyright (c) 2002 - 2007 Bruce Mayhew
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * Getting Source ==============
 * 
 * Source for this application is maintained at code.google.com, a repository
 * for free software projects.
 * 
 * For details, please see http://code.google.com/p/webgoat/
 *
 * @author asmolen
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class WsSqlInjection extends LessonAdapter
{

    public final static String ccNumber = "cc_number";

    private final static String ACCT_NUM = "account_number";

    private String accountNumber;

    final static IMG CREDITS_LOGO = new IMG("images/logos/parasoft.jpg")
	    .setAlt("Parasoft").setBorder(0).setHspace(0).setVspace(0);

    private static Connection connection = null;

    /* (non-Javadoc)
     * @see lessons.AbstractLesson#getMenuItem()
     */
    static boolean completed;


    protected Category getDefaultCategory()
    {
	return AbstractLesson.WEB_SERVICES;
    }


    protected List getHints()
    {
	List<String> hints = new ArrayList<String>();
	hints
		.add("Try connecting to the WSDL with a browser or Web Service tool.");
	hints
		.add("Sometimes the server side code will perform input validation before issuing  "
			+ "the request to the web service operation.  Try to bypass this check by "
			+ "accessing the web service directly");
	hints
		.add("The URL for the web service is: http://localhost/WebGoat/services/WsSqlInjection?WSDL <br>"
			+ "The WSDL can usually be viewed by adding a ?WSDL on the end of the request.");
	hints
		.add("Create a new soap request for the getCreditCard(String id) operation.");
	hints
		.add("A soap request uses the following HTTP header: <br> "
			+ "SOAPAction: some action header, can be &quot;&quot;<br><br>"
			+ "The soap message body has the following format:<br>"
			+ "&lt;?xml version='1.0' encoding='UTF-8'?&gt; <br>"
			+ "&nbsp;&nbsp;&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'&gt; <br>"
			+ "&nbsp;&nbsp;&nbsp;&nbsp;&lt;SOAP-ENV:Body&gt; <br>"
			+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ns1:getCreditCard SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' xmlns:ns1='http://lessons'&gt; <br>"
			+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id xsi:type='xsd:string'&gt;101&lt;/id&gt; <br>"
			+ "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ns1:getCreditCard&gt; <br>"
			+ "&nbsp;&nbsp;&nbsp;&nbsp;&lt;/SOAP-ENV:Body&gt; <br>"
			+ "&nbsp;&nbsp;&lt;/SOAP-ENV:Envelope&gt; <br>" + "");
	/*		"&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt; <br>" +
	 "  &lt;SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" <br>" +
	 "	                  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" <br>" +
	 "	                  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"&gt; <br>" +
	 "     &lt;SOAP-ENV:Body&gt; <br>" +
	 "		  &lt;ns1:getCreditCard SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:ns1=\"http://lessons\"&gt; <br>" +
	 "		   &lt;id xsi:type=\"xsd:string\"&gt;101&lt;/id&gt; <br>"+
	 "		  &lt;/ns1:getCreditCard&gt; <br>" +
	 "     &lt;/SOAP-ENV:Body&gt; <br>" +
	 "  &lt;/SOAP-ENV:Envelope&gt; <br><br>" +
	 "Intercept the HTTP request and try to create a soap request.");	*/
	return hints;
    }

    private final static Integer DEFAULT_RANKING = new Integer(150);


    protected Integer getDefaultRanking()
    {
	return DEFAULT_RANKING;
    }


    public String getTitle()
    {
	return "Web Service SQL Injection";
    }


    protected Element makeAccountLine(WebSession s)
    {
	ElementContainer ec = new ElementContainer();

	ec.addElement(new P().addElement("Enter your Account Number: "));

	accountNumber = s.getParser().getRawParameter(ACCT_NUM, "101");
	Input input = new Input(Input.TEXT, ACCT_NUM, accountNumber.toString());
	ec.addElement(input);

	Element b = ECSFactory.makeButton("Go!");
	ec.addElement(b);

	return ec;
    }


    protected Element createContent(WebSession s)
    {
	ElementContainer ec = new ElementContainer();
	try
	{
	    if (connection == null)
	    {
		connection = DatabaseUtilities.makeConnection(s);
	    }
	    ec.addElement(makeAccountLine(s));

	    String query = "SELECT * FROM user_data WHERE userid = "
		    + accountNumber;
	    ec.addElement(new PRE(query));
	    for (int i = 0; i < accountNumber.length(); i++)
	    {
		char c = accountNumber.charAt(i);
		if (c < '0' || c > '9')
		{
		    ec.addElement("Invalid account number. ");
		    accountNumber = "0";
		}
	    }
	    try
	    {
		ResultSet results = getResults(accountNumber);
		if ((results != null) && (results.first() == true))
		{
		    ResultSetMetaData resultsMetaData = results.getMetaData();
		    ec.addElement(DatabaseUtilities.writeTable(results,
			    resultsMetaData));
		    results.last();
		    if (results.getRow() >= 6)
		    {
			//this should never happen
		    }
		}
		else
		{
		    ec.addElement("No results matched.  Try Again.");
		}
	    }
	    catch (SQLException sqle)
	    {
		ec.addElement(new P().addElement(sqle.getMessage()));
	    }
	    A a = new A("services/WsSqlInjection?WSDL", "WebGoat WSDL File");
	    ec
		    .addElement(new P()
			    .addElement("Exploit the following WSDL to access sensitive data:"));
	    ec.addElement(new BR());
	    ec.addElement(a);
	    getLessonTracker(s).setCompleted(completed);
	}
	catch (Exception e)
	{
	    s.setMessage("Error generating " + this.getClass().getName());
	    e.printStackTrace();
	}
	return (ec);
    }


    public ResultSet getResults(String id)
    {
	try
	{
	    Connection connection = DatabaseUtilities.makeConnection();
	    if (connection == null)
	    {
		return null;
	    }
	    String query = "SELECT * FROM user_data WHERE userid = " + id;
	    try
	    {
		Statement statement = connection.createStatement(
			ResultSet.TYPE_SCROLL_INSENSITIVE,
			ResultSet.CONCUR_READ_ONLY);
		ResultSet results = statement.executeQuery(query);
		return results;
	    }
	    catch (SQLException sqle)
	    {}
	}
	catch (Exception e)
	{}
	return null;
    }


    public String[] getCreditCard(String id)
    {
	ResultSet results = getResults(id);
	if ((results != null))
	{
	    try
	    {
		results.last();
		String[] users = new String[results.getRow()];
		if (users.length > 4)
		{
		    completed = true;
		}
		results.beforeFirst();
		while (results.next() == true)
		{
		    int i = results.getRow();
		    users[i - 1] = results.getString(ccNumber);
		}
		return users;
	    }
	    catch (SQLException sqle)
	    {}
	}
	return null;
    }


    public Element getCredits()
    {
	return super.getCustomCredits("By Alex Smolen", CREDITS_LOGO);
    }
}
